package com.vaadin.tutorial.crm.security.authentication;

import com.vaadin.tutorial.crm.backend.repository.SysUserRepository;
import com.vaadin.tutorial.crm.backend.service.SysUserService;
import com.vaadin.tutorial.crm.security.authorization.MyAccessDecisionManager;
import com.vaadin.tutorial.crm.security.authorization.MySecurityMetadataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * 登录认证核心类
 * @Author: fan
 * @DateTime: 2021-01-15 11:06
 **/
@EnableWebSecurity
@Configuration
//@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Autowired
    SysUserService sysUserService;

    /* @Autowired
    MyAccessDecisionManager myAccessDecisionManager;
    @Autowired
    MySecurityMetadataSource mySecurityMetadataSource;*/

    private static final String LOGIN_PROCESSING_URL = "/login";
    private static final String LOGIN_FAILURE_URL = "/login?error";
    private static final String LOGIN_URL = "/login";
    private static final String LOGOUT_SUCCESS_URL = "/login";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        System.out.println(sysUserService.getUserByUsername("test"));
        http.csrf().disable()//禁用跨站点伪造请求(CSRF)保护
                .requestCache().requestCache(new CustomRequestCache()) //使用CustomRequestCache跟踪未授权的请求，以便在登录后适当地重定向用户
                .and().authorizeRequests() //打开授权
                .antMatchers("/teacher-list").hasAnyRole("ROLE_TEACHER", "ROLE_ADMIN")

                /*.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>(){
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setSecurityMetadataSource(mySecurityMetadataSource);
                        o.setAccessDecisionManager(myAccessDecisionManager);
                        return o;
                    }
                })*/

                .requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll() //允许来自Vaadin框架的所有内部文件的通信

                .anyRequest().authenticated() // 所有请求都需要认证

                .and().formLogin() //启用基于表单的登录并允许对其进行未经身份验证的访问
                .loginPage(LOGIN_URL).loginProcessingUrl(LOGIN_PROCESSING_URL).permitAll()
                .usernameParameter("username")
                .passwordParameter("password")
                .failureUrl(LOGIN_FAILURE_URL).permitAll() //配置登录失败跳转的URL
                .and().logout().logoutSuccessUrl(LOGOUT_SUCCESS_URL).permitAll(); //退出登录跳转的URL
    }


   /* //测试用户的用户名以及密码
    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        UserDetails user =
                User.withUsername("test")
                        .password("{noop}test")
                        .roles("USER")
                        .build();

        return new InMemoryUserDetailsManager(user);
    }*/

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(sysUserService).passwordEncoder(new BCryptPasswordEncoder());
    }

    //配置哪些文件的访问不需要经过以上安全策略
    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers(
                "/VAADIN/**",
                "/favicon.ico",
                "/robots.txt",
                "/manifest.webmanifest",
                "/sw.js",
                "/offline.html",
                "/icons/**",
                "/images/**",
                "/styles/**",
                "/h2-console/**");
    }
}
